# -*- coding: utf-8 -*-

import mod.server.extraServerApi as serverApi

from gemstoneScripts.config.sys import *
from gemstoneScripts.config.blockList import *
from gemstoneScripts.config.gemstonePlatform import *
from gemstoneScripts.common.gemstonePolishing import get_smooth_gemstone, GEMSTONE_DICT

ServerSystem = serverApi.GetServerSystemCls()
comp = serverApi.GetEngineCompFactory()


class Listener(ServerSystem):
    def __init__(self, namespace, system_name):
        super(ServerSystem, self).__init__(namespace, system_name)
        print '[Debug] UI 服务端注册完毕'
        self.ListenEvent()
        pass

    def Destroy(self):
        self.UnListenEvent()
        pass

    def ListenEvent(self):
        self.ListenForEvent(MOD_NAME, MOD_LISTENER + 'GemstonePlatformUI', GET_PLAYER_BAG_EVENT, self,
                            self.send_player_bag)
        self.ListenForEvent(MOD_NAME, MOD_LISTENER + 'GemstonePlatformUI', GET_GEMSTONE_PLATFORM_UI_DATA_EVENT,
                            self, self.send_ui_data)
        self.ListenForEvent(MOD_NAME, MOD_LISTENER + 'GemstonePlatformUI', SWAP_BAG_ITEM_EVENT, self,
                            self.swap_bag_item)
        self.ListenForEvent(MOD_NAME, MOD_LISTENER + 'GemstonePlatformUI', GEMSTONE_PLATFORM_SWAP_TO_INPUT,
                            self, self.swap_to_input)
        self.ListenForEvent(MOD_NAME, MOD_LISTENER + 'GemstonePlatformUI', GEMSTONE_PLATFORM_GET_OUTPUT_EVENT,
                            self, self.get_output)
        self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(),
                            'ServerPlaceBlockEntityEvent', self, self.init_gemstone_platform)
        self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), 'ServerBlockUseEvent',
                            self, self.on_open_ui)
        self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), 'ServerItemUseOnEvent',
                            self, self.add_water)
        self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), 'ServerBlockEntityTickEvent',
                            self, self.ui_tick)
        pass

    def UnListenEvent(self):
        self.UnListenForEvent(MOD_NAME, MOD_LISTENER + 'GemstonePlatformUI', GET_PLAYER_BAG_EVENT, self,
                              self.send_player_bag)
        self.UnListenForEvent(MOD_NAME, MOD_LISTENER + 'GemstonePlatformUI', GET_GEMSTONE_PLATFORM_UI_DATA_EVENT,
                              self, self.send_ui_data)
        self.UnListenForEvent(MOD_NAME, MOD_LISTENER + 'GemstonePlatformUI', SWAP_BAG_ITEM_EVENT, self,
                              self.swap_bag_item)
        self.UnListenForEvent(MOD_NAME, MOD_LISTENER + 'GemstonePlatformUI', GEMSTONE_PLATFORM_SWAP_TO_INPUT,
                              self, self.swap_to_input)
        self.UnListenForEvent(MOD_NAME, MOD_LISTENER + 'GemstonePlatformUI', GEMSTONE_PLATFORM_GET_OUTPUT_EVENT,
                              self, self.get_output)
        self.UnListenForEvent(serverApi.GetEngineSystemName(), serverApi.GetEngineNamespace(),
                              'ServerPlaceBlockEntityEvent', self, self.init_gemstone_platform)
        self.UnListenForEvent(serverApi.GetEngineSystemName(), serverApi.GetEngineNamespace(), 'ServerBlockUseEvent',
                              self, self.on_open_ui)
        self.UnListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), 'ServerItemUseOnEvent',
                              self, self.add_water)
        self.UnListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), 'ServerBlockEntityTickEvent',
                              self, self.ui_tick)
        pass

    def get_output(self, args):
        output = args['output']
        player_id = args['playerId']
        block_pos = args['pos']
        block_dim = args['dim']
        comp_item = comp.CreateItem(player_id)
        comp_block_entity = comp.CreateBlockEntityData(serverApi.GetLevelId())
        block_data = comp_block_entity.GetBlockEntityData(block_dim, block_pos)
        block_data['output'] = None
        if not comp_item.SpawnItemToPlayerInv(output, player_id):
            comp_pos = comp.CreatePos(player_id)
            comp_dim = comp.CreateDimension(player_id)
            pos = comp_pos.GetPos()
            dim = comp_dim.GetEntityDimensionId()
            comp_item_level = comp.CreateItem(serverApi.GetLevelId())
            comp_item_level.SpawnItemToLevel(output, dim, pos)
        pass

    def ui_tick(self, args):
        block_name = args['blockName']
        if block_name == GEMSTONE_PLATFORM:
            self.dispose_block_entity(args)
            self.dispose_hopper(args)
        pass

    def dispose_hopper(self, args):
        pos = (args['posX'], args['posY'] - 1, args['posZ'])
        dim = args['dimension']
        comp_block = comp.CreateBlockInfo(serverApi.GetLevelId())
        block_dic = comp_block.GetBlockNew(pos, dim)
        if block_dic:
            if block_dic['name'] == 'minecraft:hopper':
                comp_redstone = comp.CreateRedStone(serverApi.GetLevelId())
                strength = comp_redstone.GetStrength(pos, dim)
                if strength == 0:
                    comp_item = comp.CreateItem(serverApi.GetLevelId())
                    for _ in xrange(5):
                        item_dict = comp_item.GetContainerItem(pos, _, dim)
                        if not item_dict:
                            comp_block_entity = comp.CreateBlockEntityData(serverApi.GetLevelId())
                            pos_block_entity = (pos[0], pos[1] + 1, pos[2])
                            block_data = comp_block_entity.GetBlockEntityData(dim, pos_block_entity)
                            if block_data['output']:
                                comp_item.SpawnItemToContainer(block_data['output'], _, pos, dim)
                                block_data['output'] = None
        pass

    def dispose_block_entity(self, args):
        pos = (args['posX'], args['posY'], args['posZ'])
        dim = args['dimension']
        comp_block_entity = comp.CreateBlockEntityData(serverApi.GetLevelId())
        block_data = comp_block_entity.GetBlockEntityData(dim, pos)
        if not block_data['input'] or block_data['output']:
            block_data['progress'] = 0
            return
        if block_data['water'] == 0:
            return
        input_name = block_data['input']['newItemName']
        if input_name not in GEMSTONE_DICT.keys():
            return
        block_data['progress'] += 1
        block_data['water'] -= 1
        if block_data['progress'] == 200:
            if block_data['input']['count'] <= 1:
                block_data['input'] = None
            else:
                block_data['input']['count'] -= 1
            block_data['progress'] = 0
            block_data['output'] = get_smooth_gemstone(input_name)
        pass

    def add_water(self, args):
        block_name = args['blockName']
        item = args['itemDict']['newItemName']
        if block_name == GEMSTONE_PLATFORM and item == 'minecraft:water_bucket':
            comp_block_entity = comp.CreateBlockEntityData(serverApi.GetLevelId())
            pos = (args['x'], args['y'], args['z'])
            dim = args['dimensionId']
            player_id = args['entityId']
            block_data = comp_block_entity.GetBlockEntityData(dim, pos)
            if block_data['water'] <= MAX_WATER - WATER_ADD:
                block_data['water'] += WATER_ADD
            elif block_data['water'] < MAX_WATER:
                block_data['water'] = MAX_WATER
            else:
                return
            comp_item = comp.CreateItem(player_id)
            comp_game = comp.CreateGame(player_id)
            mode = comp_game.GetPlayerGameType(player_id)
            if mode == 1:
                return
            args['ret'] = True
            comp_item.SpawnItemToPlayerCarried(
                    {'newItemName': 'minecraft:bucket',
                     'newAuxValue': 0,
                     'count': 1}, player_id)
        pass

    def send_player_bag(self, args):
        player_id = args['playerId']
        bag_data = {}
        comp_item = comp.CreateItem(player_id)
        for _ in xrange(36):
            item = comp_item.GetPlayerItem(0, _, True)
            bag_data[_] = item
        self.NotifyToClient(player_id, SEND_PLAYER_BAG_DATA_EVENT, {'bagData': bag_data})
        pass

    def send_ui_data(self, args):
        dim = args['dim']
        pos = args['pos']
        player_id = args['playerId']
        comp_block_entity = comp.CreateBlockEntityData(serverApi.GetLevelId())
        block_data = comp_block_entity.GetBlockEntityData(dim, pos)
        self.NotifyToClient(player_id, SEND_GEMSTONE_PLATFORM_UI_DATA_EVENT,
                            {'input': block_data['input'],
                             'output': block_data['output'],
                             'water': block_data['water'],
                             'progress': block_data['progress']})
        pass

    def swap_to_input(self, args):
        dim = args['dim']
        pos = args['pos']
        player_id = args['playerId']
        input = args['input']
        slot = args['slot']
        comp_block_entity = comp.CreateBlockEntityData(serverApi.GetLevelId())
        comp_item = comp.CreateItem(player_id)
        block_data = comp_block_entity.GetBlockEntityData(dim, pos)
        item = comp_item.GetPlayerItem(0, slot, True)
        block_data['input'] = item
        if input:
            comp_item.SpawnItemToPlayerInv(input, player_id, slot)
            return
        comp_item.SetInvItemNum(slot, 0)
        pass

    def swap_bag_item(self, args):
        item1 = args['item']
        item2 = args['swapItem']
        player_id = args['playerId']
        comp_item = comp.CreateItem(player_id)
        comp_item.SetInvItemExchange(item1, item2)
        pass

    def init_gemstone_platform(self, args):
        block_name = args['blockName']
        if block_name == GEMSTONE_PLATFORM:
            pos = (args['posX'], args['posY'], args['posZ'])
            dim = args['dimension']
            comp_block_entity = comp.CreateBlockEntityData(serverApi.GetLevelId())
            block_data = comp_block_entity.GetBlockEntityData(dim, pos)
            block_data['input'] = None
            block_data['output'] = None
            block_data['water'] = 0
            block_data['progress'] = 0
        pass

    def on_open_ui(self, args):
        block_name = args['blockName']
        if block_name == GEMSTONE_PLATFORM:
            player_id = args['playerId']
            pos = (args['x'], args['y'], args['z'])
            dim = args['dimensionId']
            comp_item = comp.CreateItem(player_id)
            item_dic = comp_item.GetPlayerItem(2)
            if item_dic:
                if item_dic['newItemName'] == 'minecraft:water_bucket' or item_dic['newItemName'] == 'minecraft:bucket':
                    return
            comp_block_entity = comp.CreateBlockEntityData(serverApi.GetLevelId())
            block_data = comp_block_entity.GetBlockEntityData(dim, pos)
            input = block_data['input']
            output = block_data['output']
            water = block_data['water']
            progress = block_data['progress']
            self.NotifyToClient(player_id, OPEN_GEMSTONE_PLATFORM_UI_EVENT,
                                {'input': input,
                                 'output': output,
                                 'water': water,
                                 'progress': progress,
                                 'playerId': player_id,
                                 'pos': pos,
                                 'dim': dim})
        pass
